/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.example.netcracker.timer;

import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import ru.example.netcracker.model.entity.Alarm;
import ru.example.netcracker.model.entity.Notification;
import ru.example.netcracker.model.entity.Task;
import ru.example.netcracker.model.observer.Observable;
import ru.example.netcracker.model.observer.Observer;

/**
 *
 * @author Nikolay
 */
public class ServiceTimer implements Observer {

    private static final Logger LOG = Logger.getLogger(ServiceTimer.class.getName());
    
    private class ServiceTimerTask extends TimerTask {

        private final Task task;

        public ServiceTimerTask(Task task) {
            this.task = task;
        }
        
        @Override
        public void run() {
            LOG.log(Level.INFO, "Notification!!! Time: " + new Date(System.currentTimeMillis()));
            if (listener != null) {
                if (task instanceof Notification) {   
                    Notification notif = (Notification) task;
                    LOG.log(Level.DEBUG, "Task: " + notif.toString());
                    listener.onReceiveNotification(notif);                    
                }
                if (task instanceof Alarm) {
                    Alarm alarm = (Alarm) task;
                    LOG.log(Level.DEBUG, "Task: " + alarm.toString());
                    listener.onReceiveAlarm((Alarm) task);
                }
            }                
        }

    }
    
    private OnReceiveTaskListener listener;
    private Timer timer;

    public ServiceTimer() {
        this.timer = new Timer("task_manager_timer", true);   
    }

    public void schedule(Task task) {
        LOG.log(Level.INFO, "Task: " + task);
        timer.schedule(new ServiceTimerTask(task), task.getDate()); 
    }
    
    public void addOnReceiveTaskListener(OnReceiveTaskListener listener) {
        LOG.log(Level.INFO, "Listener: " + listener);
        this.listener = listener;
    }
    
    public void removeOnReceiveTaskListener() {
        LOG.log(Level.INFO, "Old Listener: " + listener);
        listener = null;
    }
    
    @Override
    public void update(Observable o, List<Task> arg) {
        LOG.log(Level.INFO, "Observable: " + o + " | arg: " + arg);
        timer.cancel();
        timer.purge();
        timer = null;
        timer = new Timer("task_manager_timer", true);
        //removeEndTask(arg);
        for(Task task : arg) {
            if(!task.isShow())
                schedule(task);
        }
    }
    
    public void removeEndTask(List<Task> tasks) {
        int size = 0;
        while (size != tasks.size()) {
            Task task = tasks.get(size);
            if (!task.isEnd()) {
                tasks.remove(task);
            } else {                
                size++;
            }
        }
        LOG.log(Level.INFO, "finish tasks: " + tasks);
    }
    
    public Task findFirstTask(List<Task> tasks) {
        long min = Long.MAX_VALUE;
        Task firstTask = null;
        int size = 0;
        while (size != tasks.size()) {
            Task task = tasks.get(size);
            long x = task.getDate().getTime() - System.currentTimeMillis();
            if (x <= 0) {
                tasks.remove(task);
            } else {
                if (min > x) {
                    min = x;
                    firstTask = task;
                }
                size++;
            }
        }
        return firstTask;
    }
    
}
